<template>
  <div class="bi-table-cross" :style="style">
    <!--    <vxe-toolbar-->
    <!--      size="medium"-->
    <!--      class="absolute w-full -top-[40px] opacity-0 hover:opacity-100"-->
    <!--      ref="toolbarRef"-->
    <!--      export-->
    <!--      print-->
    <!--    />-->
    <vxe-grid
      height="auto"
      :show-header="option.header.isHeader"
      v-bind="gridOptions"
      :header-cell-style="headerCellStyle"
      :row-style="rowStyle"
      :cell-style="cellStyle"
      :footer-cell-style="footerCellStyle"
      class="vxe-grid"
      ref="xGrid"
    />
  </div>
</template>
<script setup>
import { useVisual } from "@/hooks/userEditor"

const { commonStyle } = useVisual()
const attrs = useAttrs()
const option = attrs.option

// 整理后数据列表
const dataList = ref([])
let { dimension, columnDimension, measure } = attrs.data
const gridOptions = ref({})
const init = () => {
  let columns = []
  if (columnDimension.length > 0) {
    const pivotData = pivot(
      dataList.value,
      dimension.map((v) => v.title),
      columnDimension.map((v) => v.title),
      measure.map((v) => v.title)
    )
    columns = pivotData.columns
    //冻结左列
    if (option.freezeColumnLeft > 0) {
      for (let i = 0; i < this.option.freezeColumnLeft; i++) {
        columns[i].fixed = "left"
      }
    }
    //冻结右列
    if (option.freezeColumnRight > 0) {
      for (let i = 0; i < option.freezeColumnRight; i++) {
        columns[columns.length - 1 - i].fixed = "right"
      }
    }
    dataList.value = pivotData.data
  } else {
    columns = [...dimension, ...measure].map((item) => {
      return {
        field: item.title,
        title: item.title,
        minWidth: 100,
        align: option.header.textAlign,
        sortable: true
      }
    })
  }
  // 是否显示序号
  if (option.showIndex) {
    columns.unshift({
      type: "seq",
      title: "序号",
      width: option.indexWidth,
      align: "center"
    })
  }
  gridOptions.value = {
    border: option.body.border.type,
    stripe: true,
    "scroll-x": { enabled: true, gt: 10 },
    "scroll-y": { enabled: true, gt: 500 },
    printConfig: {},
    exportConfig: {},
    columnConfig: {
      resizable: true
    },
    columns,
    ...option,
    showFooter: option.total.showTotal,
    footerMethod
  }
  if (xGrid.value) {
    xGrid.value.loadData(dataList.value)
  }
}
watch(
  attrs.data,
  (val) => {
    dimension = val.dimension
    measure = val.measure
    columnDimension = val.columnDimension
    init()
  },
  { deep: true }
)
watch(
  [option, commonStyle],
  () => {
    init()
  },
  { deep: true }
)
// 表格样式
const style = computed(() => {
  const body = { ...option.body }
  let style = {
    color: commonStyle.value.theme === "dark" ? "#000" : "#fff"
  }
  if (commonStyle.value.fontFamily) {
    style.fontFamily = commonStyle.value.fontFamily
  }
  body.fontSize = body.fontSize ? body.fontSize + "px" : "auto"
  if (!body.color) {
    body.color = "#000"
  }
  style = { ...style, ...body }
  style["--vxe-table-border-width"] = option.body.border.width + "px"
  style["--vxe-table-border-color"] = option.body.border.color
  style["--vxe-table-body-background-color"] = option.body.oddRowBackgroundColor
  style["--vxe-table-row-striped-background-color"] = option.body.evenRowBackgroundColor
  return style
})
const headerCellStyle = computed(() => {
  // 循环对象过滤空值
  const header = Object.keys(option.header).reduce((obj, key) => {
    if (option.header[key]) {
      obj[key] = option.header[key]
    }
    return obj
  }, {})
  header.height = header.height ? header.height + "px" : "auto"
  return { ...style.value, ...header }
})
const rowStyle = computed(() => {
  return style.value
})
const cellStyle = computed(() => {
  return style.value
})

// 尾部样式
const footerCellStyle = computed(() => {
  const total = Object.keys(option.total).reduce((obj, key) => {
    if (option.total[key]) {
      obj[key] = option.total[key]
    }
    return obj
  }, {})
  return {
    ...style.value,
    ...total,
    height: total.height ? total.height + "px" : "auto"
  }
})
const footerMethod = ({ data, columns }) => {
  if (dataList.value.length === 0) {
    return []
  }
  return [
    columns.map((column, columnIndex) => {
      if (columnIndex === 0) {
        return option.total.text
      }
      if (measure.map((v) => v.title).includes(column.field)) {
        const find = measure.find((v) => v.title === column.field)
        let format = find.format
        if (option.decimal) {
          format = option.decimal
        }
        try {
          if (format.includes("PERCENT")) {
            format = g.getNum(format)
          }
        } catch (error) {
          /* empty */
        }
        let aggregate = "sum"
        if (find.aggregate === "AVG") {
          aggregate = "avg"
        }
        const sum = g[aggregate](data, column.field)[column.field]
        return sum ? (format > 0 ? sum.toFixed(format) : sum) : ""
      }
      return ""
    })
  ]
}
// 表格结束
const xGrid = ref(null)
const toolbarRef = ref(null)
nextTick(() => {
  // 将表格和工具栏进行关联
  const $table = xGrid.value
  const $toolbar = toolbarRef.value
  if ($table && $toolbar) {
    $table.connect($toolbar)
  }
})

// 组装pivot
const pivot = (res, rowDim, columnDim, target, totalDim = []) => {
  const mergeData = {}
  const data = []
  const nest = yang.nest()
  rowDim.forEach((d) => nest.key((i) => i[d]))
  // totalDim.forEach((d) => nest.key((i) => i[d]));
  nest.rollup((leaves) => {
    const obj = {}
    leaves.forEach((l) => {
      const keys = []
      rowDim.forEach((t) => {
        obj[t] = l[t]
      })
      totalDim.reduce((a, b) => {
        //累加
        obj[b] = (+obj[b] || 0) + (+l[b] || 0)
      }, 0)
      columnDim.forEach((t) => {
        keys.push(l[t])
      })
      target.forEach((v) => {
        const num = l[v] ? l[v] * 1 : 0
        const key = keys.join("") + v
        obj[key] = num
        const ks = []
        keys.forEach((k) => {
          ks.push(k)
          if (obj[ks.join("") + "小计"]) {
            obj[ks.join("") + "小计"] += num
          } else {
            obj[ks.join("") + "小计"] = num
          }
        })
      })
    })
    // if (option.isshowsubcolsummary) {
    //   if (target.length === 1) {
    //     obj['小计'] = yang[option.totalColFormula](leaves, (d) => +d[target[0]])
    //   } else {
    //     target.forEach((v) => {
    //       obj[v] = yang[option.totalColFormula](leaves, (d) => +d[v])
    //     })
    //   }
    // }
    data.push(obj)
    //增加小计
    return leaves
  })
  nest.entries(res)
  const columnNest = yang.nest()
  columnDim.forEach((d) =>
    columnNest.key((i) => {
      return i[d]
    })
  )
  columnNest.rollup((leaves) => {
    const result = []
    const obj = {}
    leaves.forEach((l) => {
      columnDim.forEach((t) => {
        obj[t] = l[t]
      })
    })
    target.forEach((v) => {
      let item = {
        field: Object.values(obj).join("") + v,
        title: v,
        minWidth: 100,
        align: option.header.textAlign,
        sortable: true,
        // width: option.colList[v] ? option.colList[v] : 'auto',
        // formatter: this.formatterNum,
        children: [],
        // type: 'html',
        params: {}
      }
      item = { ...item, ...option.header }
      if (target.length > 1) {
        item.params.title = v
        item.params.params = obj
      } else {
        item.params = obj
      }
      result.push(item)
    })
    return result
  })
  //小计表头
  mergeData.columns = g.T.toSigntree(columnNest.entries(res, "title", "children", "children"))
  g.T.getLevelNodes(mergeData.columns)
  // if (target.length === 1) {
  //   let subTotalsDimensionsColumn = []
  //   option.subTotalsDimensionsCol.forEach((item) => {
  //     subTotalsDimensionsColumn.push(columnDim.findIndex((i) => i === item))
  //   })
  //   mergeData.columns = this.mergeLastNode(mergeData.columns, columnDim.length - 1, subTotalsDimensionsColumn)
  // }
  // if (zuanFlag) {
  //   let zuanField = this.config.zuan[this.config.zuanLevel]
  //   rowParamList.splice(this.zuanIndex, 1, zuanField)
  // }
  const tableColumn = [...dimension].map((item) => {
    return {
      ...{
        field: item.title,
        title: item.title,
        minWidth: 100,
        align: option.header.textAlign,
        sortable: true,
        // formatter: describeHtml || '',
        // type: 'html',
        params: {
          title: item.title
        }
      },
      ...option.header
    }
  })
  // let totalParamList = totalDim.map((item) => {
  //   return {
  //     field: item,
  //     title: item,
  //     sortable: true,
  //     width: this.option.colList[item] ? this.option.colList[item] : 'auto',
  //     minWidth: '10%',
  //     formatter: this.formatterNum,
  //     type: 'html',
  //     params: {
  //       title: item.columnTitle
  //     }
  //   }
  // })
  mergeData.columns = [...tableColumn, ...mergeData.columns]
  //合计
  if (option.showFooter) {
    if (!option.subTotalsDimensionsCol.includes(columnDim[0])) {
      if (target.length === 1) {
        if (option.colposition === "2") {
          mergeData.columns.push({
            field: "小计",
            title: this.option.coltitle ? this.option.coltitle : "小计",
            sortable: true,
            width: "auto",
            minWidth: "10%",
            formatter: this.formatterColNum,
            type: "html"
          })
        } else {
          mergeData.columns.splice(rowDim.length, 0, {
            field: "小计",
            title: this.option.coltitle ? this.option.coltitle : "小计",
            sortable: true,
            width: "auto",
            minWidth: "10%",
            formatter: this.formatterColNum,
            type: "html"
          })
        }
      } else {
        const children = []
        target.forEach((v) => {
          children.push({
            field: v,
            title: v,
            minWidth: 100,
            align: option.header.textAlign,
            sortable: true
          })
        })
        if (this.option.colposition === "2") {
          mergeData.columns.push({
            field: "小计",
            title: this.option.coltitle ? this.option.coltitle : "小计",
            sortable: true,
            width: "auto",
            minWidth: "10%",
            formatter: this.formatterColNum,
            children,
            type: "html"
          })
        } else {
          mergeData.columns.splice(rowDim.length, 0, {
            field: "小计",
            title: option.coltitle ? option.coltitle : "小计",
            minWidth: 100,
            align: option.header.textAlign,
            sortable: true,
            // formatter: this.formatterColNum,
            children
          })
        }
      }
    }
  }
  mergeData.columns = [...mergeData.columns]
  mergeData.data = data
  return mergeData
}
// 对外暴露的方法，接收外部传入的数据
const update = (data) => {
  dataList.value = data.data
  if (data.data) {
    dataList.value = dataList.value.map((item) => {
      Object.values(item).forEach((v, i) => {
        if (option.decimal) {
          if (measure.map((v) => v.title).includes(Object.keys(item)[i])) {
            item[Object.keys(item)[i]] = v.toFixed(option.decimal)
          }
        }
        if (option.emptyCellText) {
          if (v === null || v === undefined || v === "" || !v) {
            item[Object.keys(item)[i]] = option.emptyCellText
          }
        }
      })
      return item
    })
  }
  init()
}
defineExpose({
  update
})
</script>
<style scoped lang="less">
.bi-table-cross {
  width: 100%;
  height: 100%;
  .vxe-grid {
    width: 100%;
    height: 100%;
  }
  :deep(.vxe-toolbar) {
    background-color: #ffc10700 !important;
    color: #fff !important;
  }
  :deep(.vxe-toolbar--export) {
    .vxe-button {
      background-color: #ffc10700 !important;
      color: #fff !important;
    }
  }
  :deep(.vxe-button:not(.is--disabled)) {
    color: v-bind("style.background") !important;
  }
}
</style>
